package com.ruoyi.eqmonitor.service.impl;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import breeze.framework.reflect.Reflector;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.DictUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.eqmonitor.dispose.service.MqttService;
import com.ruoyi.eqmonitor.domain.OptDevice;
import com.ruoyi.eqmonitor.domain.OptDeviceAndRelation;
import com.ruoyi.eqmonitor.domain.OptDeviceRelation;
import com.ruoyi.eqmonitor.dtos.*;
import com.ruoyi.eqmonitor.mapper.OptDeviceMapper;
import com.ruoyi.eqmonitor.service.IOptDeviceMonitorConfigService;
import com.ruoyi.eqmonitor.service.IOptDeviceRelationService;
import com.ruoyi.eqmonitor.service.IOptDeviceService;
import com.ruoyi.eqmonitor.utils.Constant;
import com.ruoyi.eqmonitor.vo.OptDeviceVo;
import com.ruoyi.system.api.RemoteFileService;
import com.ruoyi.system.api.domain.SysDictData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import static com.ruoyi.eqmonitor.utils.Constant.MQTT_HARDWARE_TYPES;


/**
 * 设备管理Service业务层处理
 *
 * @author ruoyi
 * @date 2022-11-25
 */
@Slf4j
@Service
@Order(value = 1)
public class OptDeviceServiceImpl extends ServiceImpl<OptDeviceMapper, OptDevice> implements IOptDeviceService {

    /** 设备redis缓存key */
    public static final String DEVICE_REDIS_KEY = "opt_device";
    /** 真实设备redis缓存key */
    public static final String REAL_DEVICE_REDIS_KEY = "opt_real_device";

    @Resource
    private RedisService redisService;

    /** 是否接入物联网消息队列 */
    @Value("${mqtt.enable:false}")
    private boolean enableMqtt;

    @Lazy
    @Resource
    private MqttService mqttService;

    @Resource
    private IOptDeviceMonitorConfigService monitorConfigService;

    @Resource
    private IOptDeviceRelationService iOptDeviceRelationService;

    @Autowired
    private RemoteFileService remoteFileService;

    /**
     * 初始化方法 初始化所有设备
     */
    @PostConstruct
    public void init() {
        refreshRedisCache();
    }

    @Override
    public boolean refreshCache() {
        // 刷新设备缓存
        boolean flag = refreshRedisCache();
        if (enableMqtt) {
            log.info("刷新缓存 - 重新订阅mqtt开始!");
            // 断开连接
            flag  = flag && mqttService.disConnect();
            // 重新连接
            flag  = flag && mqttService.connect(true);
            // 重新订阅
            flag  = flag && mqttService.subScription();
            log.info("刷新缓存 - 重新订阅mqtt结束!");
        }
        return flag;
    }

    private boolean refreshRedisCache() {
        log.info("初始化设备缓存开始!");
        List<OptDeviceDto> list = baseMapper.selectOptDeviceList(new OptDeviceDto());
        for (OptDeviceDto optDeviceDto : list) {
            if (optDeviceDto != null) {
                setSingleFile("videoId","videoFile", optDeviceDto);
            }
        }
        redisService.deleteObject(DEVICE_REDIS_KEY);
        redisService.deleteObject(REAL_DEVICE_REDIS_KEY);
        for (OptDeviceDto optDevice : list) {
            redisService.setCacheMapValue(DEVICE_REDIS_KEY, optDevice.getDeviceCode(), optDevice);
        }
        for (OptDeviceDto optDevice : list) {
            redisService.setCacheMapValue(REAL_DEVICE_REDIS_KEY, optDevice.getRealDeviceCode(), optDevice);
        }
        log.info("初始化设备缓存完毕!");
        return true;
    }

    @Override
    public OptDeviceDto selectOptDeviceById(Long id){
        OptDeviceDto optDeviceDto = baseMapper.selectOptDeviceById(id);
        if (optDeviceDto != null) {
            setSingleFile("videoId","videoFile", optDeviceDto);
        }
        return optDeviceDto;
    }

    @Override
    public OptDeviceRelation getDeviceAndRelation(Long id) {
        OptDeviceDto optDeviceDto = selectOptDeviceById(id);
        if (ObjectUtil.isNull(optDeviceDto)) {
            return null;
        }
        setSingleFile("videoId","videoFile", optDeviceDto);
        OptDeviceRelation relation = iOptDeviceRelationService.getByCode(optDeviceDto.getDeviceCode());
        OptDeviceAndRelation optDeviceAndRelation = new OptDeviceAndRelation();
        BeanUtil.copyProperties(optDeviceDto, optDeviceAndRelation);
        BeanUtil.copyProperties(relation, optDeviceAndRelation);
        return relation;
    }

    @Override
    public List<OptDeviceDto> selectOptDeviceList(OptDeviceDto optDevice){
        List<OptDeviceDto> deviceList = baseMapper.selectOptDeviceList(optDevice);
        for (OptDeviceDto optDeviceDto : deviceList) {
            if (optDeviceDto != null) {
                setSingleFile("videoId","videoFile", optDeviceDto);
            }
        }
        return deviceList;
    }

    /**
     * 根据设备编码获取设备数据
     * @param code 设备编码
     */
    @Override
    public OptDeviceDto getDeviceByCode(String code) {
        if (StrUtil.isEmpty(code)) {
            return null;
        }
        OptDeviceDto optDevice = redisService.getCacheMapValue(DEVICE_REDIS_KEY, code);
        if (optDevice == null) {
            optDevice = baseMapper.selectOptDeviceByCode(code);
            if (optDevice != null) {
                setSingleFile("videoId","videoFile", optDevice);
            }
        }
        return optDevice;
    }

    /**
     * 根据设备编码获取设备数据
     * @param code 设备编码
     */
    @Override
    public OptDeviceDto getDeviceByRealCode(String code) {
        if (StrUtil.isEmpty(code)) {
            return null;
        }
        OptDeviceDto optDevice = redisService.getCacheMapValue(REAL_DEVICE_REDIS_KEY, code);
        if (optDevice == null) {
            optDevice = baseMapper.selectOptDeviceByRealCode(code);
            if (optDevice != null) {
                setSingleFile("videoId","videoFile", optDevice);
            }
        }
        return optDevice;
    }

    /**
     * 新增设备 同时添加到缓存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveDevice(OptDevice optDevice) {
        if (getDeviceCodeCount(optDevice.getDeviceCode(), null) > 0) {
            throw new ServiceException("设备编码已存在");
        }
        if (getRealDeviceCodeCount(optDevice.getRealDeviceCode(), null) > 0) {
            throw new ServiceException("真实设备编码已存在");
        }
        if (!ArrayUtil.contains(MQTT_HARDWARE_TYPES, optDevice.getAccessType())) {
            // 校验一级主题(GW 或 ND)
            throw new RuntimeException("接入类型" + optDevice.getAccessType() + "不合法");
        }
        if (StrUtil.isEmpty(optDevice.getRealDeviceCode()) || optDevice.getRealDeviceCode().length() < 6) {
            // 校验二级主题 (6位snCode编码)
            throw new RuntimeException("真实设备编码" + optDevice.getRealDeviceCode() + "不合法, 必须为6位");
        }
        optDevice.setCreateTime(new Date());
        optDevice.setCreateBy(SecurityUtils.getUsername());
        int rows = baseMapper.insert(optDevice);
        if (rows > 0) {
            // 设备加入缓存
            redisService.setCacheMapValue(DEVICE_REDIS_KEY, optDevice.getDeviceCode(), optDevice);
            redisService.setCacheMapValue(REAL_DEVICE_REDIS_KEY, optDevice.getRealDeviceCode(), optDevice);
            // 进行订阅
            if (enableMqtt) {
                mqttService.subScription(optDevice.getRealDeviceCode(), optDevice.getAccessType());
            }
        }
        return rows;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveDeviceAndRelation(OptDeviceAndRelation deviceAndRelation) {
        OptDevice optDevice = BeanUtil.copyProperties(deviceAndRelation, OptDevice.class);
        OptDeviceRelation relation = BeanUtil.copyProperties(deviceAndRelation, OptDeviceRelation.class);
        if (getDeviceCodeCount(optDevice.getDeviceCode(), null) > 0) {
            throw new ServiceException("设备编码已存在");
        }
        if (getRealDeviceCodeCount(optDevice.getRealDeviceCode(), null) > 0) {
            throw new ServiceException("真实设备编码已存在");
        }
        if (!ArrayUtil.contains(MQTT_HARDWARE_TYPES, optDevice.getAccessType())) {
            // 校验一级主题(GW 或 ND)
            throw new RuntimeException("接入类型" + optDevice.getAccessType() + "不合法");
        }
        if (StrUtil.isEmpty(optDevice.getRealDeviceCode()) || optDevice.getRealDeviceCode().length() < 6) {
            // 校验二级主题 (6位snCode编码)
            throw new RuntimeException("真实设备编码" + optDevice.getRealDeviceCode() + "不合法, 必须为6位");
        }
        // 先新增设备关联关系
        iOptDeviceRelationService.saveDeviceRelation(relation);

        // 再新增所属设备
        optDevice.setCreateTime(new Date());
        optDevice.setCreateBy(SecurityUtils.getUsername());
        int rows = baseMapper.insert(optDevice);
        if (rows > 0) {
            OptDeviceDto optDeviceDto = selectOptDeviceById(optDevice.getId());
            // 设备加入缓存
            redisService.setCacheMapValue(DEVICE_REDIS_KEY, optDevice.getDeviceCode(), optDeviceDto);
            redisService.setCacheMapValue(REAL_DEVICE_REDIS_KEY, optDevice.getRealDeviceCode(), optDeviceDto);
            // 进行订阅
            if (enableMqtt) {
                mqttService.subScription(optDevice.getRealDeviceCode(), optDevice.getAccessType());
            }
        }
        return rows;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDeviceAndRelation(OptDeviceAndRelation deviceAndRelation) {
        OptDevice optDevice = BeanUtil.copyProperties(deviceAndRelation, OptDevice.class);
        OptDeviceRelation relation = BeanUtil.copyProperties(deviceAndRelation, OptDeviceRelation.class);

        if (getDeviceCodeCount(optDevice.getDeviceCode(), optDevice.getId()) > 0) {
            throw new ServiceException("设备编码已存在");
        }
        if (getRealDeviceCodeCount(optDevice.getRealDeviceCode(), optDevice.getId()) > 0) {
            throw new ServiceException("真实设备编码已存在");
        }
        if (!ArrayUtil.contains(MQTT_HARDWARE_TYPES, optDevice.getAccessType())) {
            // 校验一级主题(GW 或 ND)
            throw new RuntimeException("接入类型" + optDevice.getAccessType() + "不合法");
        }
        if (StrUtil.isEmpty(optDevice.getRealDeviceCode()) || optDevice.getRealDeviceCode().length() < 6) {
            // 校验二级主题 (6位snCode编码)
            throw new RuntimeException("真实设备编码" + optDevice.getRealDeviceCode() + "不合法, 必须为6位");
        }
        OptDevice oldDevice = getById(optDevice.getId());
        // 不允许修改设备编码
        if (!oldDevice.getDeviceCode().equals(optDevice.getDeviceCode())) {
            throw new ServiceException("设备编码不允许修改");
        }
        // 先修改设备关系
        iOptDeviceRelationService.updateDeviceRelation(relation);
        // 再修改设备
        optDevice.setUpdateTime(new Date());
        optDevice.setUpdateBy(SecurityUtils.getUsername());
        int rows = baseMapper.updateById(optDevice);
        if (rows > 0) {
            // 真实设备编码改变 则重新刷新缓存
            if (!oldDevice.getRealDeviceCode().equals(optDevice.getRealDeviceCode())) {
                // 删除旧的设备编码对应的设备
                redisService.deleteCacheMapValue(REAL_DEVICE_REDIS_KEY, oldDevice.getRealDeviceCode());
            }
            OptDeviceDto optDeviceDto = selectOptDeviceById(optDevice.getId());
            // 添加新的设备
            redisService.setCacheMapValue(DEVICE_REDIS_KEY, optDevice.getDeviceCode(), optDeviceDto);
            // 添加新的设备 真实设备编码缓存
            redisService.setCacheMapValue(REAL_DEVICE_REDIS_KEY, optDevice.getRealDeviceCode(), optDeviceDto);
            // 进行订阅
            if (enableMqtt) {
                // 如果接入类型或设备编码发生改变 则取消原本的订阅 重新订阅新的设备
                if (!StrUtil.equals(oldDevice.getRealDeviceCode(), optDevice.getRealDeviceCode()) ||
                        !StrUtil.equals(oldDevice.getAccessType(), optDevice.getAccessType())
                ) {
                    mqttService.unSubScription(oldDevice.getRealDeviceCode(), oldDevice.getAccessType());
                    mqttService.subScription(optDevice.getRealDeviceCode(), optDevice.getAccessType());
                }
            }
        }
        return rows;
    }

    /**
     * 修改设备 同时添加到缓存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDeviceById(OptDevice optDevice) {
        if (getDeviceCodeCount(optDevice.getDeviceCode(), optDevice.getId()) > 0) {
            throw new ServiceException("设备编码已存在");
        }
        if (getRealDeviceCodeCount(optDevice.getRealDeviceCode(), optDevice.getId()) > 0) {
            throw new ServiceException("真实设备编码已存在");
        }
        if (!ArrayUtil.contains(MQTT_HARDWARE_TYPES, optDevice.getAccessType())) {
            // 校验一级主题(GW 或 ND)
            throw new RuntimeException("接入类型" + optDevice.getAccessType() + "不合法");
        }
        if (StrUtil.isEmpty(optDevice.getRealDeviceCode()) || optDevice.getRealDeviceCode().length() < 6) {
            // 校验二级主题 (6位snCode编码)
            throw new RuntimeException("真实设备编码" + optDevice.getRealDeviceCode() + "不合法, 必须为6位");
        }
        OptDevice oldDevice = getById(optDevice.getId());
        // 不允许修改设备编码
        if (!oldDevice.getDeviceCode().equals(optDevice.getDeviceCode())) {
            throw new ServiceException("设备编码不允许修改");
        }
        optDevice.setUpdateTime(new Date());
        optDevice.setUpdateBy(SecurityUtils.getUsername());
        int rows = baseMapper.updateById(optDevice);
        if (rows > 0) {
            // 真实设备编码改变 则重新刷新缓存
            if (!oldDevice.getRealDeviceCode().equals(optDevice.getRealDeviceCode())) {
                // 删除旧的设备编码对应的设备
                redisService.deleteCacheMapValue(REAL_DEVICE_REDIS_KEY, oldDevice.getRealDeviceCode());
            }
            // 添加新的设备
            redisService.setCacheMapValue(DEVICE_REDIS_KEY, optDevice.getDeviceCode(), optDevice);
            // 添加新的设备 真实设备编码缓存
            redisService.setCacheMapValue(REAL_DEVICE_REDIS_KEY, optDevice.getRealDeviceCode(), optDevice);
            // 进行订阅
            if (enableMqtt) {
                // 如果接入类型或设备编码发生改变 则取消原本的订阅 重新订阅新的设备
                if (!StrUtil.equals(oldDevice.getRealDeviceCode(), optDevice.getRealDeviceCode()) ||
                        !StrUtil.equals(oldDevice.getAccessType(), optDevice.getAccessType())
                ) {
                    mqttService.unSubScription(oldDevice.getRealDeviceCode(), oldDevice.getAccessType());
                    mqttService.subScription(optDevice.getRealDeviceCode(), optDevice.getAccessType());
                }
            }
        }
        return rows;
    }

    /**
     * 批量删除设备
     * @param ids 设备ids
     * @return 删除行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteDevice(List<Long> ids) {
        List<OptDevice> optDevices = listByIds(ids);
        // 删除自己
        int rows = baseMapper.deleteBatchIds(ids);
        // 删除设备阈值
        monitorConfigService.removeDeviceMonitorConfigByDevice(optDevices);
        for (OptDevice optDevice : optDevices) {
            // 删除缓存
            redisService.deleteCacheMapValue(DEVICE_REDIS_KEY, optDevice.getDeviceCode());
            // 删除真实设备缓存
            redisService.deleteCacheMapValue(REAL_DEVICE_REDIS_KEY, optDevice.getRealDeviceCode());
            // 删除设备关系
            iOptDeviceRelationService.deleteByDeviceCode(optDevice.getDeviceCode());
            if (enableMqtt) {
                // 取消订阅
                mqttService.unSubScription(optDevice.getRealDeviceCode(), optDevice.getAccessType());
            }
        }
        return rows;
    }

    /**
     * 查询指定设备编码重复出现的次数 传入id则过滤id不为此值的设备编码
     * @param deviceCode 设备编码
     * @param id 不包含的id
     * @return 出现次数
     */
    @Override
    public long getDeviceCodeCount(String deviceCode, Long id) {
        LambdaQueryWrapper<OptDevice> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(OptDevice::getDeviceCode, deviceCode);
        wrapper.ne(ObjectUtil.isNotNull(id), OptDevice::getId, id);
        return count(wrapper);
    }

//    @Override
//    public long getDeviceTypeCount(String name,List<String> deviceTypes) {
//        final LambdaQueryWrapper<OptDevice> lqw = new LambdaQueryWrapper<>();
////        lqw.like(OptDevice::get)
//        lqw.in(OptDevice::getDeviceType,deviceTypes);
//        return count(lqw);
//    }

    /**
     * 查询指定设备真设备编码重复出现的次数 传入id则过滤id不为此值的设备编码
     * @param realDeviceCode 设备编码
     * @param id 不包含的id
     * @return 出现次数
     */
    @Override
    public long getRealDeviceCodeCount(String realDeviceCode, Long id) {
        LambdaQueryWrapper<OptDevice> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(OptDevice::getRealDeviceCode, realDeviceCode);
        wrapper.ne(ObjectUtil.isNotNull(id), OptDevice::getId, id);
        return count(wrapper);
    }

    /**
     * 查询设备数量统计
     * @return 出现次数
     */
    @Override
    public List<OptDeviceQuantityCountDto> selectOptDeviceQuantity(AlarmSearchInput inputs) {
        return baseMapper.selectOptDeviceQuantity(inputs);
    }

    /**
     * 查询设备数量统计
     * @return 出现次数
     */
    @Override
    public List<OptDeviceAndAlarmCountDto> selectOptDeviceAlarmQuantity(AlarmSearchInput inputs) {
        List<SysDictData> optDeviceTypes = DictUtils.getDictCache("opt_device_type");
        if (CollectionUtil.isEmpty(optDeviceTypes)) return ListUtil.empty();
        List<OptDeviceAlarmCountDto> optDeviceAlarmCountDtos = baseMapper.selectOptDeviceAlarmQuantity(inputs);
        List<OptDeviceQuantityCountDto> optDeviceQuantityCountDtos = selectOptDeviceQuantity(inputs);

        List<OptDeviceAndAlarmCountDto> resultList = new ArrayList<>();
        Map<String, OptDeviceAlarmCountDto> collect1 = optDeviceAlarmCountDtos.stream()
                .collect(Collectors.toMap(OptDeviceAlarmCountDto::getDeviceType, Function.identity()));
        Map<String, OptDeviceQuantityCountDto> collect2 = optDeviceQuantityCountDtos.stream()
                .collect(Collectors.toMap(OptDeviceQuantityCountDto::getDeviceType, Function.identity()));

        for (SysDictData optDeviceType : optDeviceTypes) {
            OptDeviceAndAlarmCountDto temp = new OptDeviceAndAlarmCountDto();
            temp.setDeviceType(optDeviceType.getDictValue());
            temp.setDeviceTypeName(optDeviceType.getDictLabel());
            OptDeviceAlarmCountDto optDeviceAlarmCountDto = collect1.get(optDeviceType.getDictValue());
            OptDeviceQuantityCountDto optDeviceQuantityCountDto = collect2.get(optDeviceType.getDictValue());
            temp.setAlarmCount(optDeviceAlarmCountDto == null ? 0 : optDeviceAlarmCountDto.getDeviceCount());
            temp.setDeviceCount(optDeviceQuantityCountDto == null ? 0 : optDeviceQuantityCountDto.getDeviceCount());
            resultList.add(temp);
        }
        return resultList;
    }

    @Override
    public List<OptDeviceDto> getBzFlowDevice() {
        return baseMapper.selectPumpStationDeviceList(ListUtil.of(Constant.EquipmentType.SR500_L_Y0_LD.getCode()));
    }

    /**
     * 查询泵站周边的设备
     */
    @Override
    public List<OptDeviceDto> selectPumpStationDeviceList(List<String> deviceTypes) {
        return baseMapper.selectPumpStationDeviceList(deviceTypes);
    }

    @Override
    public List<OptDeviceDto> selectOptDeviceListAndLastTime(OptDeviceDto optDeviceDto) {
        return baseMapper.selectOptDeviceListAndLastTime(optDeviceDto);
    }

    @Override
    public List<OptDeviceDto> getByDeviceType(Integer state,List<String> siteNames) {
        OptDeviceDto optDeviceDto = new OptDeviceDto();
        List<String> list = new ArrayList<>();
        if (state == 0 || state == 3)  {
            list.add(Constant.EquipmentType.SE200_L_Y0.getCode());
        }else if (state == 1){
            list.add(Constant.EquipmentType.SE200_L_Y0.getCode());
            //list.add(Constant.EquipmentType.SR500_L_Y0_LDN.getCode());
        }else if (state == 2){
            //list.add(Constant.EquipmentType.SR500_L_Y0_LDN.getCode());
        }
        optDeviceDto.setDeviceTypes(list);
        optDeviceDto.setSiteNames(siteNames);
        return baseMapper.selectOptDeviceList(optDeviceDto);
    }

    @Override
    public List<OptDeviceDto> getByDeviceTypes(OptDeviceDto optDeviceDto) {
        return baseMapper.selectOptDeviceList(optDeviceDto);
    }

    @Override
    public List<StreetAlarmResultDto> selectStreetAlarm(AlarmSearchInput inputs) {
        return baseMapper.selectStreetAlarm(inputs);
    }

    @Override
    public List<StreetAlarmResultDto> selectStreetSubAlarm(AlarmSearchInput inputs) {
        return baseMapper.selectStreetSubAlarm(inputs);
    }

    @Override
    public Map<String, List<OptDeviceVo>> getAll(Integer state) {
        HashMap<String, List<OptDeviceVo>> map = new HashMap<>();
        List<OptDeviceVo> list = baseMapper.getAll(state);
        Map<String, List<OptDeviceVo>> collect = list.stream().collect(Collectors.groupingBy(OptDeviceVo::getDeviceType));
        List<OptDeviceVo> optDeviceVos = new ArrayList<>();
        for (String key : collect.keySet()){
            String s = null;
            switch (key){
                case "SE200-L-Y0":
                    s = "一杆式河道监测站";
                    break;
                case "SJ500-L-Y0":
                    s = "井盖状态监测仪";
                    break;
                case "SR500-L-Y0-LD":
                    s = "管道流量监测仪";
                    break;
                case "SR500-L-Y0-LDN":
                    s = "氨氮一体机";
                    break;
                case "SY800-L-Y0":
                    s = "排水管网流量监测+液位监测仪";
                    break;
                case "SR500-L-Y0-SNY":
                    optDeviceVos.addAll(collect.get(key));
                    break;
                case "SR500-L-Y0-STE":
                    optDeviceVos.addAll(collect.get(key));
                    break;
                case "SR500-L-Y0-SYT":
                    optDeviceVos.addAll(collect.get(key));
                    break;
            }
            if (s != null){
                map.put(s,collect.get(key));
            }
        }
        map.put("原位水质监测仪",optDeviceVos);
        return map;
    }

    @Override
    public List<OptDeviceDto> selectOnOffLine(OnOffLineDto dto) {
        String deviceType = dto.getDeviceType();
        OptDeviceDto optDeviceDto = new OptDeviceDto();
        optDeviceDto.setDeviceType(deviceType);
        List<OptDeviceDto> optDeviceDtos = this.selectOptDeviceListAndLastTime(optDeviceDto);
        Integer state = dto.getState();
        //当前时间
        long time = new Date().getTime() / 1000 / 60 / 60;
        if (state == 0){    //全部设备
            return optDeviceDtos;
        }else {
            List<OptDeviceDto> vo = new ArrayList<>();
            for (OptDeviceDto deviceDto : optDeviceDtos){
                long time1;
                //设备最后回传数据时间
                if(deviceDto.getDeviceLastTime() == null){
                    time1 = Long.MAX_VALUE;
                }else {
                    time1 = deviceDto.getDeviceLastTime().getTime() / 1000 / 60 / 60;
                }
                //设备掉线周期（小时）
                Integer offLineTime = deviceDto.getOffLineTime();
                long l = time - time1;
                if (state == 1){    //在线设备
                    if (l < offLineTime){
                        vo.add(deviceDto);
                    }
                }else {     //离线设备
                    if (l > offLineTime){
                        vo.add(deviceDto);
                    }
                }
            }
            return vo;
        }
    }
    @Override
    public List<OptDeviceDto> selectOnOffLineBySensorType(OnOffLineDto dto) {
        String sensorType = dto.getSensorType();
        OptDeviceDto optDeviceDto = new OptDeviceDto();
        optDeviceDto.setSensorType(sensorType);
        List<OptDeviceDto> optDeviceDtos = this.selectOptDeviceListAndLastTime(optDeviceDto);
        Integer state = dto.getState();
        //当前时间
        long time = new Date().getTime() / 1000 / 60 / 60;
        if (state == 0){    //全部设备
            return optDeviceDtos;
        }else {
            List<OptDeviceDto> vo = new ArrayList<>();
            for (OptDeviceDto deviceDto : optDeviceDtos){
                long time1;
                //设备最后回传数据时间
                if(deviceDto.getDeviceLastTime() == null){
                    time1 = 0;
                }else {
                    time1 = deviceDto.getDeviceLastTime().getTime() / 1000 / 60 / 60;
                }
                //设备掉线周期（小时）
                Integer offLineTime = deviceDto.getOffLineTime();
                long l = time - time1;
                if (state == 1){    //在线设备
                    if (l < offLineTime){
                        vo.add(deviceDto);
                        if("".equals(sensorType)&&deviceDto.getDeviceCode().equals("587BCL")){
                            vo.add(deviceDto);
                        }
                    }
                }else {     //离线设备
                    if (l > offLineTime){
                        vo.add(deviceDto);
                        if(deviceDto.getDeviceCode().equals("587BCL")){
                            vo.add(deviceDto);
                        }
                    }
                }
            }
            return vo;
        }
    }

    @Override
    public List<OptDevice> listByDeviceType(String deviceType) {
        LambdaQueryWrapper<OptDevice> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(OptDevice::getDeviceType, deviceType);
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public OptDevice selectOptDeviceNewById(Long id){
        return baseMapper.selectOptDeviceNewById(id);
    }

    @Override
    public List<OptDevice> selectOptDeviceNewList(OptDevice optDeviceNew){
        return baseMapper.selectOptDeviceNewList(optDeviceNew);
    }

    //    @Override
//    public boolean toLeadJSON(InputStream inputStream) throws Exception {
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        String sFile = FileUtil.ReadFile((FileInputStream) inputStream);
//        JSONObject jsonObject = JSON.parseObject(sFile);
//        Object features = jsonObject.get("features");
//        String featuresString = JSONArray.toJSONString(features);
//        List<String> featuresList= JSONArray.parseArray(featuresString,String.class);
//        ArrayList<OptDeviceNew> list = new ArrayList<>();
//        for (String s : featuresList){
//            JSONObject sjsonObject = JSON.parseObject(s);
//            Object properties = sjsonObject.get("properties");
//            String s1 = properties.toString();
//            JSONObject map = JSON.parseObject(s1);
//            OptDeviceNew deviceNew = new OptDeviceNew();
//            deviceNew.setSnId(map.get("sn编码").toString());
//            deviceNew.setName(map.get("产品名").toString());
//            deviceNew.setType(map.get("产品型").toString());
//            deviceNew.setSiteId(map.get("站点ID").toString());
//            deviceNew.setSiteName(map.get("站点名").toString());
//            deviceNew.setSiteCode(map.get("站点编").toString());
//            String installTimeString = map.get("安装时").toString();
//            Date parse = sdf.parse(installTimeString);
//            deviceNew.setInstallTime(parse);
//            deviceNew.setLocation(map.get("位置").toString());
//            deviceNew.setGcjX(map.get("GCJ02经").toString());
//            deviceNew.setGcjY(map.get("GCJ02纬").toString());
//            deviceNew.setWgsX(map.get("WGS84经").toString());
//            deviceNew.setWgsY(map.get("WGS84纬").toString());
//            deviceNew.setTOWN(map.get("TOWN").toString());
//            list.add(deviceNew);
//        }
//        //批量导入
//        return this.saveBatch(list);
//    }

    @Override
    public Map<String, List<OptDevice>> getAll() {
        List<OptDevice> optDeviceNews = baseMapper.selectOptDeviceNewList(null);
        return optDeviceNews.stream().collect(Collectors.groupingBy(OptDevice::getDeviceType));
    }

    @Override
    public List<OptDevice> backstageDeviceSum(Integer state, String areaName) {
        List<String> deviceTypeList = new ArrayList<>();
        /*switch (state){
            case 1://溢流井总设备
                deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_LDN.getCode());
                break;
            case 2://水质总设备 或 管网入流入渗设备
                deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_LDN.getCode());
                deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_SNY.getCode());
                deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_STE.getCode());
                deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_SYT.getCode());
                break;
            case 3://管网淤堵设备
                deviceTypeList.add(Constant.EquipmentType.SY800_L_Y0.getCode());
                deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_SYT.getCode());
                deviceTypeList.add(Constant.EquipmentType.SR500_L_Y0_STE.getCode());
                break;
        }*/
        return baseMapper.backstageDeviceSum(areaName,deviceTypeList);
    }

    @Override
    public List<Map<String, String>> mySelectCount(String areaName) {
        return baseMapper.mySelectCount(areaName);
    }

    @Override
    public List<OptPointDto> selectOptPointList() {
        return baseMapper.selectOptPointList();
    }

    @Override
    public List<OptDeviceDto> selectOptDeviceListBySiteId(String siteId, List<String> sensorTypeList) {
        return baseMapper.selectOptDeviceListBySiteId(siteId, sensorTypeList);
    }


    @Override
    public JSONObject getCountJson(String sensorType) {
        JSONObject object = new JSONObject();
        OnOffLineDto dto = new OnOffLineDto();
        dto.setState(1);
        dto.setSensorType(sensorType);
        object.put("total",this.countBySensorType(sensorType));
        object.put("online",this.selectOnOffLineBySensorType(dto).size());
        return object;
    }
    @Override
    public int countBySensorType(String s) {
        return baseMapper.countBySensorType(s);
    }

    private void setSingleFile(String idProperty,String fileProperty,Object obj) {
        Object propertyValue = Reflector.getProperty(obj, idProperty);
        if(null != propertyValue && !"".equals(propertyValue.toString())) {
            try {
                Long fileId = Long.parseLong(propertyValue.toString());
                Reflector.setProperty(obj, fileProperty, remoteFileService.getInfo(fileId).getData());
            } catch (Exception e) {
            }
        }

    }
}
